package com.ridu.project.beshid.service.impl;

import com.google.common.collect.Sets;
import com.ridu.project.beshid.api.GeneralResponse;
import com.ridu.project.beshid.api.Status;
import com.ridu.project.beshid.api.User;
import com.ridu.project.beshid.config.Global;
import com.ridu.project.beshid.entity.JifenEntity;
import com.ridu.project.beshid.entity.UserEntity;
import com.ridu.project.beshid.repository.UserRepository;
import com.ridu.project.beshid.service.JifenService;
import com.ridu.project.beshid.service.UserService;
import com.ridu.project.beshid.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;

/**
 * Created by Administrator on 2017/1/13.
 */
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository repository;
    @Autowired
    private JifenService jifenService;

    @Override
    public GeneralResponse<User> createUser(UserEntity user) {
        GeneralResponse<User> response = new GeneralResponse<>();
        try {
            if (repository.findByUsername(user.getUsername()) != null) {
                response.setStatus(Status.FAILED);
                response.setMessage("用户名已存在");
                return response;
            }
            String salt1 = new Date().toString();
            user.setPassword(new Sha256Hash(user.getPassword(), salt1).toBase64());
            user.setSalt(salt1);
            repository.saveAndFlush(user);
            response.setStatus(Status.SUCCESS);
        } catch (Exception e) {
            response.setStatus(Status.FAILED);
            response.setMessage(e.getMessage());
            log.error("创建用户异常", e);
        }
        return response;
    }

    @Override
    public UserEntity findByUsername(String username) {
        return repository.findByUsername(username);
    }

    /**
     * 同updateUser
     */
    @Override
    public GeneralResponse<User> changeUser(Long userId, String newPassword, String category, String role) {
        GeneralResponse<User> response = new GeneralResponse<>();
        try {
            UserEntity u = repository.findById(userId).get();
            u.setPassword(new Sha256Hash(newPassword, u.getSalt()).toBase64());
            u.setRoles(role);
            if(!StringUtil.isEmpty(category)){
                u.setPlatform(category);
            }
            repository.save(u);
            response.setStatus(Status.SUCCESS);
        } catch (Exception e) {
            response.setStatus(Status.FAILED);
            response.setMessage(e.getMessage());
            log.error("修改密码异常", e);
        }
        return response;
    }

    @Override
    public GeneralResponse<User> getAllUsers(int currentPage, int pageSize) {
        GeneralResponse<User> response = new GeneralResponse<>();
        try {
            if (currentPage == 0) {
                currentPage = 1;
            }
            if (pageSize == 0) {
                pageSize = Global.DEFAULT_PAGE_SIZE;
            }
            Sort sort = new Sort(Sort.Direction.DESC, "id");
            Pageable pageable = new PageRequest(currentPage - 1, pageSize, sort);
            Page<UserEntity> page = repository.findAll(new Specification<UserEntity>() {
                @Override
                public Predicate toPredicate(Root<UserEntity> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    Predicate isDelete = null;
                    isDelete = cb.equal(root.<Boolean>get("deleted"), false);
                    query.where(isDelete);
                    return null;
                }
            }, pageable);
            List<User> userList = new ArrayList<>();
            page.getContent().forEach(userEntity -> {
                User user = new User();
                BeanUtils.copyProperties(userEntity, user);
                userList.add(user);
                JifenEntity entity = jifenService.findByUsername(user.getUsername());
                if(entity != null){
                    user.setTransactionHash(entity.getTransactionHash());
                }
            });
            response.setRows(userList);
            response.setTotal(page.getTotalElements());
        } catch (Exception e) {
            response.setMessage(e.getMessage());
            response.setStatus(Status.FAILED);
        }
        return response;
    }


    @Override
    public GeneralResponse<String> batchDelStatus(Boolean status, String ids) {
        GeneralResponse<String> response = new GeneralResponse<>();
        try {
            if (StringUtils.isBlank(ids)) {
                response.setStatus(Status.FAILED);
                response.setMessage("ids is empty");
            } else {
                String[] item = ids.split(",");
                List<UserEntity> listItem = new ArrayList<>();
                for (String id : item) {
                    UserEntity u = repository.findById(Long.parseLong(id)).get();
                    if (!u.getUsername().equals("administrator")) {
                        listItem.add(u);
                    }
                }
                repository.deleteInBatch(listItem);
                response.setTotal(listItem.size());
                response.setStatus(Status.SUCCESS);
            }

        } catch (Exception e) {
            log.error("用户删除异常", e);
            response.setStatus(Status.FAILED);
            response.setMessage(e.getMessage());
        }
        return response;
    }

    @Override
    public Set<String> findRoles(String username) {
        Set<String> result = Sets.newHashSet();
        UserEntity userEntity = findByUsername(username);
        if (userEntity != null && userEntity.getRoles() != null && userEntity.getRoles().length() > 0) {
            Arrays.stream(userEntity.getRoles().split(",")).forEach(roleString -> result.add(roleString));
        }
        return result;
    }
}
